using System.Linq;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem;
using Xunit;

namespace Framework.Tests.Refactoring
{
    public class ConstructorTreeTest
    {
        internal interface IDependency { }

        internal class Dependency : IDependency { }

        public class TestCtorTarget
        {
            public TestCtorTarget()
                : this("a")
            {

            }

            public TestCtorTarget(string s)
                : this(s, false)
            {

            }

            public TestCtorTarget(string s, bool t) : this(s, t, new Dependency()) { }
            internal TestCtorTarget(string s, bool t, IDependency dependency) { }

            public TestCtorTarget(bool t, string s) : this(t, s, new Dependency()) { }
            internal TestCtorTarget(bool t, string s, IDependency dependency)
            {

            }
        }

        public class TestCtorLegacy
        {
            public TestCtorLegacy()
                : this("a")
            {

            }

            public TestCtorLegacy(string s)
                : this(s, false)
            {

            }


            public TestCtorLegacy(string s, bool t)
            {

            }

            public TestCtorLegacy(bool t, string s)
            {

            }
        }

        private readonly CSharpParser parser;

        public ConstructorTreeTest()
        {
            parser = new CSharpParser();
        }

        [Fact]
        public void Should_return_constructor_without_initializer()
        {
            var syntaxTree = parser.Parse(@"
namespace Framework.Tests.Refactoring
{
    public class TestCtorLegacy
    {
        public TestCtorLegacy()
            : this(""a"")
        {

        }

        public TestCtorLegacy(string s)
            : this(s, false)
        {

        }


        public TestCtorLegacy(string s, bool t)
        {

        }

        public TestCtorLegacy(bool t, string s)
        {

        }
    }
}
");

            var rootConstructors = syntaxTree.Descendants.OfType<ConstructorDeclaration>().Where(NotThis);

            Assert.Equal(2, rootConstructors.Count());

            //Add Dependency
            //Add case when there is no constructor
            //Visibility of dependency >= contructor visibility
            //Dump and initialize root constructors

        }

        private static bool NotThis(ConstructorDeclaration constructorDeclaration)
        {
            return constructorDeclaration.Initializer.ConstructorInitializerType != ConstructorInitializerType.This;
        }

        [Fact]
        //TODO : FIXME should return false instead of true
        public void Should_resolve_unresolved_types_from_modules()
        {
            var syntaxTree = parser.Parse(@"
namespace Framework.Tests.Refactoring
{
    internal interface IDependency
    {
        void JustDoIt();
    }

    internal class Dependency : IDependency
    {
        public void JustDoIt()
        {
            throw new NotImplementedException();
        }
    }

    public class ClassWithMutltipleConstructors
    {
        private readonly IDependency dependency;
        private readonly IPouet session;

        //This is Root Constructor
        internal ClassWithMutltipleConstructors(IDependency dependency, IPouet session)
        {
            this.dependency = dependency;
            this.session = session;
        }

        //This is Child Constructor
        public ClassWithMutltipleConstructors()
            : this(new Dependency())
        {

        }
    }
}
");

            //var constructors = syntaxTree.Descendants.OfType<ConstructorDeclaration>();

            //Assert.Equal(2, constructors.Count());

            syntaxTree.FileName = "toto.cs";

            IProjectContent project = new CSharpProjectContent();

            var unresolvedFiles = syntaxTree.ToTypeSystem();

            Assert.Equal(0, unresolvedFiles.Errors.Count);

            var compilation = project.CreateCompilation();

            var resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFiles);

            var result = resolver.Resolve(syntaxTree);

            Assert.False(result.IsError);
        }
    }
}